home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / devel / vbcc-wos-src / pasm / directives.c next >
C/C++ Source or Header  |  1999-01-01  |  27KB  |  1,133 lines

  1. /* $VER: pasm directives.c V1.1d (27.09.98)
  2.  *
  3.  * This file is part of pasm, a portable PowerPC assembler.
  4.  * Copyright (c) 1997-98  Frank Wille
  5.  *
  6.  * pasm is freeware and part of the portable and retargetable ANSI C
  7.  * compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann.
  8.  * pasm may be freely redistributed as long as no modifications are
  9.  * made and nothing is charged for it. Non-commercial usage is allowed
  10.  * without any restrictions.
  11.  * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
  12.  * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
  13.  *
  14.  *
  15.  * v1.1d  (27.09.98) phx
  16.  *        Allow blanks after string constants.
  17.  * v1.1c  (22.09.98) phx
  18.  *        Include file name was trashed (allocstring() was missing).
  19.  * v1.1b  (05.07.98) phx
  20.  *        Introduced section flags SF_CHIP and SF_FAST for EHF/ADos. They
  21.  *        are set by the new section attributes "C" and "F".
  22.  * v1.1   (19.06.98) phx
  23.  *        New directive .sdreg which sets the small data base
  24.  *        register (default r2).
  25.  *        .SDREG replaces the obsolete .BASEREL directive!
  26.  * v1.0   (04.04.98) phx
  27.  *        Hack in _uahalf() to make ADDR16-relocation work for instructions.
  28.  * v0.8   (14.02.98) phx
  29.  *        Alignment list for each section. This fixes the problems
  30.  *        with optimizations.
  31.  * v0.6   (30.10.97) phx
  32.  *        The names of macros will be converted to lower case (otherwise,
  33.  *        they would remain inaccessible ;)
  34.  * v0.5   (12.10.97) phx
  35.  *        .set directive is allowed multiple times on the same symbol.
  36.  *        If a .set-assignment can't be resolved in pass 1, the symbol
  37.  *        is no longer undefined, but defined with an absolute default
  38.  *        value of '1'. So .ifdef will work correctly.
  39.  *        .globl directive declares unknown symbols in pass 1 as
  40.  *        externally defined. If the symbol is defined later in the
  41.  *        source, it will be made global by add_symbol()/tables.c.
  42.  * v0.4   (29.04.97) phx
  43.  *        .new_section sets type of section-symbol to SYMI_SECTION.
  44.  *        New directives: .baserel
  45.  * v0.3   (10.04.97) phx
  46.  *        Some vbcc-specific changes.
  47.  * v0.2   (25.03.97) phx
  48.  *        Writes ELF object for 32-bit PowerPC big-endian. Either absolute
  49.  *        or ELF output format may be selected. ELF is default for all
  50.  *        currently supported platforms. PPCasm supports nine different
  51.  *        relocation types (there are much more...).
  52.  *        Compiles and works also under NetBSD/amiga (68k).
  53.  *        Changed function declaration to 'new style' in all sources
  54.  *        (to avoid problems with '...' for example).
  55.  *        Floating pointer support. New directives: .fail, .ident, .file,
  56.  *        .float, .ufloat, .double, .udouble, .local.
  57.  * v0.1   (11.03.97) phx
  58.  *        First test version with all PowerPC instructions and most
  59.  *        important directives. Only raw, absolute output.
  60.  *        .ident and .file directives are supported, but have no effect.
  61.  *        Especially floating point directives are missing.
  62.  * v0.0   (21.02.97) phx
  63.  *        File created.
  64.  */
  65.  
  66.  
  67. #define DIRECTIVES_C
  68. #include "ppcasm.h"
  69.  
  70.  
  71. void activate_section(struct GlobalVars *,struct Section *);
  72. void alignment(struct GlobalVars *,unsigned long);
  73. char escchar(char);
  74.  
  75. static void start_section(struct GlobalVars *,struct ParsedLine *pl,bool);
  76. static char *section_attributes(struct GlobalVars *,char *,uint8 *,
  77.                                 uint8 *,uint8 *,uint8 *);
  78. static void _uahalf(struct GlobalVars *,struct ParsedLine *);
  79. static void _uaword(struct GlobalVars *,struct ParsedLine *);
  80. static void uafloat(struct GlobalVars *,struct ParsedLine *,bool);
  81. static void ifeqs(struct GlobalVars *,struct ParsedLine *,int);
  82. static void ifdef(struct GlobalVars *,struct ParsedLine *,bool);
  83.  
  84.  
  85.  
  86. static void _new_section(struct GlobalVars *gv,struct ParsedLine *pl)
  87. {
  88.   start_section(gv,pl,1);
  89. }
  90.  
  91.  
  92. static void _section(struct GlobalVars *gv,struct ParsedLine *pl)
  93. {
  94.   start_section(gv,pl,0);
  95. }
  96.  
  97.  
  98. static void start_section(struct GlobalVars *gv,struct ParsedLine *pl,
  99.                           bool force_new)
  100. /* define a new section with new attributes or reactivate a */
  101. /* previously defined one */
  102. {
  103.   struct Section *nexts,*sec = (struct Section *)gv->sectionlist.first;
  104.   struct Symbol *sym;
  105.   struct AlignPoint *ap;
  106.   char *s,*name;
  107.   uint8 type,flags,protection,alignment;
  108.  
  109.   s = getarg(gv,pl->operand);  /* section's name */
  110.   name = remquotes(gv->strbuf);
  111.  
  112.   while (nexts = (struct Section *)sec->n.next) {
  113.     if (!strcmp(name,sec->name)) {
  114.  
  115.       if (force_new) {  /* overwrite an old section with the same name? */
  116.         sprintf(gv->strbuf,"%s_%08lx",sec->name,(unsigned long)sec);
  117.         name = sec->name;
  118.         sec->name = allocstring(gv->strbuf);
  119.         break;
  120.       }
  121.  
  122.       else {  /* reactivate old section with the same name */
  123.         s = section_attributes(gv,s,&type,&flags,&protection,&alignment);
  124.         if (type != ST_UNDEFINED)  /* attributes specified? */
  125.           if (sec->type!=type || sec->flags!=flags ||
  126.               sec->protection!=protection || sec->alignment!=alignment)
  127.             error(16);  /* section attributes don't match */
  128.         pl->type = OT_SECTION;
  129.         pl->opcode = (void *)sec;
  130.         activate_section(gv,sec);
  131.         checkEOL(s);
  132.         return;
  133.       }
  134.  
  135.     }
  136.     sec = nexts;
  137.   }
  138.  
  139.   /* create a new section */
  140.   sec = alloczero(sizeof(struct Section));
  141.   sec->name = allocstring(name);
  142.   s = section_attributes(gv,s,&sec->type,&sec->flags,&sec->protection,
  143.                          &sec->alignment);
  144.   if (sec->type == ST_UNDEFINED) {  /* set default attributes */
  145.     sec->type = ST_DATA;
  146.     sec->protection = SP_READ|SP_WRITE;
  147.     sec->alignment = 2;
  148.   }
  149.   initlist(&sec->reloclist);
  150.   initlist(&sec->xreflist);
  151.   ap = alloc(sizeof(struct AlignPoint));
  152.   ap->next = NULL;
  153.   ap->offset = ap->gap = 0;
  154.   ap->val = 1 << sec->alignment;
  155.   sec->first_align = sec->current_align = ap;
  156.   addtail(&gv->sectionlist,&sec->n);
  157.   pl->type = OT_SECTION;
  158.   pl->opcode = (void *)sec;
  159.   activate_section(gv,sec);
  160.   sym = add_symbol(gv,sec->name,SYM_RELOC,0);
  161.   sym->info = SYMI_SECTION;
  162.   checkEOL(s);
  163. }
  164.  
  165.  
  166. void activate_section(struct GlobalVars *gv,struct Section *sec)
  167. {
  168.   gv->csect = sec;  /* set active section */
  169.   gv->lcsym->relsect = sec;
  170.   gv->lcsym->value = sec->pc;
  171. }
  172.  
  173.  
  174. static char *section_attributes(struct GlobalVars *gv,char *s,uint8 *t,
  175.                                 uint8 *f,uint8 *p,uint8 *a)
  176. /* fill in section attributes, if specified */
  177. {
  178.   char c,*attr;
  179.  
  180.   *t = ST_UNDEFINED;
  181.   *f = *p = *a = 0;
  182.   s = skipspaces(s);
  183.   if (*s) {
  184.     if (*s == ',') {
  185.       s = skipspaces(++s);
  186.       s = getarg(gv,s);
  187.       c = *gv->strbuf;
  188.       if (c=='\"' || c=='\'') {
  189.         attr = remquotes(gv->strbuf);
  190.         while (c = *attr++) {
  191.           switch (c) {
  192.             /* contents type */
  193.             case 'c':
  194.               *t = ST_CODE;
  195.               break;
  196.             case 'd':
  197.               *t = ST_DATA;
  198.               break;
  199.             case 'u':
  200.               *t = ST_UDATA;
  201.               *f |= SF_UNINITIALIZED;
  202.               break;
  203.             case 'i':
  204.               *t = ST_STRUCT;
  205.               *f |= SF_DISCARD|SF_UNINITIALIZED;
  206.               break;
  207.             /* protection */
  208.             case 'r':
  209.               *p |= SP_READ;
  210.               break;
  211.             case 'w':
  212.               *p |= SP_WRITE;
  213.               break;
  214.             case 'x':
  215.               *p |= SP_EXEC;
  216.               break;
  217.             case 's':
  218.               *p |= SP_SHARE;
  219.               break;
  220.             case 'n': /* remove and discard currently not supported */
  221.             case 'R':
  222.               break;
  223.             case 'C':
  224.               *f |= SF_CHIP;
  225.               break;
  226.             case 'F':
  227.               *f |= SF_FAST;
  228.               break;
  229.             default:
  230.               if (c>='0' && c <='6')
  231.                 *a = (uint8)(c-'0');  /* alignment */
  232.               else
  233.                 error(15,c);  /* illegal section attribute */
  234.               break;
  235.           }
  236.         }
  237.       }
  238.       else
  239.         error(14);  /* string constant expected */
  240.     }
  241.     else if (*s != '#')
  242.       error(12);  /* colon expected */
  243.   }
  244.   return (s);
  245. }
  246.  
  247.  
  248. static void _set(struct GlobalVars *gv,struct ParsedLine *pl)
  249. {
  250.   char *s = getsymbol(gv,pl->operand);
  251.   struct Expression exp;
  252.   struct Section *cs;
  253.   char setname[STRBUFSIZE];
  254.   struct Symbol *sym;
  255.  
  256.   if (*gv->strbuf) {
  257.     strcpy(setname,gv->strbuf);
  258.     if (s = check_comma(s)) {
  259.       s = eval_expression(gv,&exp,s);
  260.       if (exp.type != SYM_UNDEF) {
  261.         if (exp.type != SYM_EXTERN) {
  262.           if (exp.type == SYM_RELOC) {
  263.             if (exp.reloctype == R_PPC_ADDR32) {
  264.               if (sym = search_symbol(gv,setname)) {
  265.                 sym->value = exp.value;
  266.                 sym->type = SYM_RELOC;
  267.                 sym->relsect = exp.symbol->relsect;
  268.               }
  269.               else {
  270.                 cs = gv->csect;
  271.                 gv->csect = exp.symbol->relsect;
  272.                 add_symbol(gv,setname,SYM_RELOC,exp.value);
  273.                 gv->csect = cs;
  274.               }
  275.             }
  276.             else
  277.               error(29);  /* can't assign relocatable half word */
  278.           }
  279.           else {
  280.             if (sym = search_symbol(gv,setname)) {
  281.               sym->value = exp.value;
  282.               sym->type = SYM_ABS;
  283.             }
  284.             else
  285.               add_symbol(gv,setname,SYM_ABS,exp.value);
  286.           }
  287.         }
  288.         else
  289.           error(28);  /* can't assign external symbol */
  290.       }
  291.       else {
  292.         if (gv->pass)  /* expression still undefined in pass 2 ? */
  293.           error(19);  /* undefined symbol */
  294.         else if (!search_symbol(gv,setname))
  295.           /* set value to 1 if unknown in first pass */
  296.           add_symbol(gv,setname,SYM_ABS,1);
  297.       }
  298.       checkEOL(s);
  299.       return;
  300.     }
  301.   }
  302.   else
  303.     error(17);  /* missing argument */
  304. }
  305.  
  306.  
  307. static void _macro(struct GlobalVars *gv,struct ParsedLine *pl)
  308. {
  309.   struct Macro *mac = alloczero(sizeof(struct Macro));
  310.   char *s = getsymbol(gv,pl->operand);
  311.  
  312.   mac->name = allocstring(gv->strbuf);
  313.   lower_case(mac->name);  /* convert macro name to lower case */
  314.   mac->text = gv->cthread->srcptr;
  315.   mac->nlines = gv->absline + 1;
  316.   gv->cthread->macskip = mac;
  317.   pl->type = OT_IGNORE;  /* ignore in pass 2 */
  318.   checkEOL(s);
  319. }
  320.  
  321.  
  322. static void _include(struct GlobalVars *gv,struct ParsedLine *pl)
  323. {
  324.   char *s;
  325.  
  326.   if (!gv->pass) {  /* pass 1 */
  327.     s = getarg(gv,pl->operand);  /* include file's name */
  328.  
  329.     /* recursively call pass 1 and create new SourceThread */
  330.     pass1(gv,include_source(gv,allocstring(remquotes(gv->strbuf))),
  331.                             NULL,gv->cthread);
  332.     checkEOL(s);
  333.   }
  334.  
  335.   else  /* recursively call pass 2 */
  336.     pass2(gv,get_source(gv),NULL,gv->cthread);
  337. }
  338.  
  339.  
  340. void alignment(struct GlobalVars *gv,unsigned long a)
  341. {
  342.   unsigned long x = (1<<a) - 1;
  343.   unsigned long pc, oldpc = gv->csect->pc;
  344.   struct AlignPoint *ap = gv->csect->current_align;
  345.  
  346.   pc = (oldpc + x) & ~x;
  347.   if (!gv->pass) {
  348.     if (ap->next)
  349.       ierror("Current alignment point is not the last one!");
  350.     ap->next = alloc(sizeof(struct AlignPoint));
  351.     ap = ap->next;
  352.     ap->next = NULL;
  353.     ap->offset = oldpc;
  354.     ap->val = 1 << a;
  355.     ap->gap = pc - oldpc;
  356.     gv->csect->current_align = ap;
  357.     gv->csect->pc = pc;
  358.   }
  359.   else {
  360.     if (!(gv->csect->current_align = ap->next))  /* next alignment section */
  361.       ierror("No more alignments in list!");
  362.     store_space(gv,pc-oldpc);
  363.   }
  364. }
  365.  
  366.  
  367. static void _align(struct GlobalVars *gv,struct ParsedLine *pl)
  368. {
  369.   char *s;
  370.   uint32 a=2;
  371.   static uint8 na=0;
  372.  
  373.   if (pl->flags & PLF_ALIGN) {
  374.     if (++na > 2)
  375.       gv->vc = TRUE;
  376.   }
  377.   else
  378.     na = 0;
  379.   s = getintexp(gv,pl->operand,&a);
  380.   alignment(gv,a);
  381.   gv->alignflag = TRUE;
  382.   if (!gv->pass)
  383.     checkEOL(s);
  384. }
  385.  
  386.  
  387. static void _space(struct GlobalVars *gv,struct ParsedLine *pl)
  388. {
  389.   char *s;
  390.   uint32 n=0;
  391.  
  392.   s = getintexp(gv,pl->operand,&n);
  393.   if (!gv->pass) {
  394.     pcadd(gv,n);
  395.     checkEOL(s);
  396.   }
  397.   else
  398.     store_space(gv,n);
  399. }
  400.  
  401.  
  402. char escchar(char c)
  403. /* convert escape code */
  404. {
  405.   switch (c) {
  406.     case 'b':
  407.       c = 8;
  408.       break;
  409.     case 'f':
  410.       c = 12;
  411.       break;
  412.     case 'n':
  413.       c = 10;
  414.       break;
  415.     case 'r':
  416.       c = 13;
  417.       break;
  418.     case 't':
  419.       c = 8;
  420.       break;
  421.   }
  422.   return (c);
  423. }
  424.  
  425.  
  426. static void _byte(struct GlobalVars *gv,struct ParsedLine *pl)
  427. {
  428.   char *s = pl->operand;
  429.   char *sb,c;
  430.   uint8 pass = gv->pass;
  431.   uint32 i;
  432.  
  433.   for (;;) {
  434.     if ((c = *s) == '\"') {  /* read string */
  435.       s = getarg(gv,s);
  436.       sb = remquotes(gv->strbuf);
  437.       if (!pass)
  438.         while (c = *sb++) {
  439.           if (c=='\\' || c=='\"')
  440.             if (*sb++ == 0)
  441.               break;
  442.           pcadd(gv,1);
  443.         }
  444.       else
  445.         while (c = *sb++) {
  446.           if (c == '\\') {
  447.             if (!(c = escchar(*sb++)))
  448.               break;
  449.           }
  450.           else if (c == '\"') {
  451.             if (!(c = *sb++))
  452.               break;
  453.           }
  454.           store_byte(gv,(uint8)c);
  455.         }
  456.       s = skipspaces(s);
  457.     }
  458.  
  459.     else {  /* get integer expression */
  460.       if (c==0 || c=='#') {
  461.         error(17);  /* missing argument */
  462.         break;
  463.       }
  464.       if (!pass) {
  465.         s = skipexpression(gv,s);
  466.         pcadd(gv,1);
  467.       }
  468.       else {
  469.         s = getintexp(gv,s,&i);
  470.         store_byte(gv,(uint8)i);
  471.         s = skipspaces(s);
  472.       }
  473.     }
  474.  
  475.     c = *s++;
  476.     if (c==0 || c=='#')  /* no more arguments? */
  477.       break;
  478.     if (c != ',') {
  479.       error(12);  /* colon expected */
  480.       break;
  481.     }
  482.     s = skipspaces(s);
  483.   }
  484. }
  485.  
  486.  
  487. static void _string(struct GlobalVars *gv,struct ParsedLine *pl)
  488. {
  489.   char *s = pl->operand;
  490.   char *sb,c;
  491.   uint8 pass = gv->pass;
  492.  
  493.   for (;;) {
  494.     if ((c = *s) == '\"') {  /* read string */
  495.       s = getarg(gv,s);
  496.       sb = remquotes(gv->strbuf);
  497.       if (!pass) {
  498.         while (c = *sb++) {
  499.           if (c=='\\' || c=='\"')
  500.             if (*sb++ == 0)
  501.               break;
  502.           pcadd(gv,1);
  503.         }
  504.         pcadd(gv,1);
  505.       }
  506.       else {
  507.         while (c = *sb++) {
  508.           if (c == '\\') {
  509.             if (!(c = escchar(*sb++)))
  510.               break;
  511.           }
  512.           else if (c == '\"') {
  513.             if (!(c = *sb++))
  514.               break;
  515.           }
  516.           store_byte(gv,(uint8)c);
  517.         }
  518.         store_byte(gv,0);
  519.       }
  520.       s = skipspaces(s);
  521.     }
  522.     else {
  523.       error(14);  /* string constant expected */
  524.       break;
  525.     }
  526.  
  527.     c = *s++;
  528.     if (c==0 || c=='#')  /* no more arguments? */
  529.       break;
  530.     if (c != ',') {
  531.       error(12);  /* colon expected */
  532.       break;
  533.     }
  534.     s = skipspaces(s);
  535.   }
  536. }
  537.  
  538.  
  539. static void _half(struct GlobalVars *gv,struct ParsedLine *pl)
  540. {
  541.   alignment(gv,1);
  542.   _uahalf(gv,pl);
  543. }
  544.  
  545.  
  546. static void _uahalf(struct GlobalVars *gv,struct ParsedLine *pl)
  547. {
  548.   char *s = pl->operand;
  549.   char *sb,c;
  550.   uint8 pass = gv->pass;
  551.   uint32 i;
  552.  
  553.   for (;;) {
  554.     c = *s;
  555.     if (c==0 || c=='#') {
  556.       error(17);  /* missing argument */
  557.       break;
  558.     }
  559.     if (!pass) {
  560.       s = skipexpression(gv,s);
  561.       pcadd(gv,2);
  562.     }
  563.     else {
  564.       gv->csect->pc -= 2;
  565.       s = getexp(gv,s,&i,2);
  566.       gv->csect->pc += 2;
  567.       store_half(gv,(uint16)i);
  568.       s = skipspaces(s);
  569.     }
  570.  
  571.     c = *s++;
  572.     if (c==0 || c=='#')  /* no more arguments? */
  573.       break;
  574.     if (c != ',') {
  575.       error(12);  /* colon expected */
  576.       break;
  577.     }
  578.     s = skipspaces(s);
  579.   }
  580. }
  581.  
  582.  
  583. static void _word(struct GlobalVars *gv,struct ParsedLine *pl)
  584. {
  585.   alignment(gv,2);
  586.   _uaword(gv,pl);
  587. }
  588.  
  589.  
  590. static void _uaword(struct GlobalVars *gv,struct ParsedLine *pl)
  591. {
  592.   char *s = pl->operand;
  593.   char *sb,c;
  594.   uint8 pass = gv->pass;
  595.   uint32 i;
  596.  
  597.   for (;;) {
  598.     c = *s;
  599.     if (c==0 || c=='#') {
  600.       error(17);  /* missing argument */
  601.       break;
  602.     }
  603.     if (!pass) {
  604.       s = skipexpression(gv,s);
  605.       pcadd(gv,4);
  606.     }
  607.     else {
  608.       s = getexp(gv,s,&i,4);
  609.       store_word(gv,i);
  610.       s = skipspaces(s);
  611.     }
  612.  
  613.     c = *s++;
  614.     if (c==0 || c=='#')  /* no more arguments? */
  615.       break;
  616.     if (c != ',') {
  617.       error(12);  /* colon expected */
  618.       break;
  619.     }
  620.     s = skipspaces(s);
  621.   }
  622. }
  623.  
  624.  
  625. static void _float(struct GlobalVars *gv,struct ParsedLine *pl)
  626. {
  627.   alignment(gv,2);
  628.   uafloat(gv,pl,FALSE);
  629. }
  630.  
  631.  
  632. static void _uafloat(struct GlobalVars *gv,struct ParsedLine *pl)
  633. {
  634.   uafloat(gv,pl,FALSE);
  635. }
  636.  
  637.  
  638. static void _double(struct GlobalVars *gv,struct ParsedLine *pl)
  639. {
  640.   alignment(gv,3);
  641.   uafloat(gv,pl,TRUE);
  642. }
  643.  
  644.  
  645. static void _uadouble(struct GlobalVars *gv,struct ParsedLine *pl)
  646. {
  647.   uafloat(gv,pl,TRUE);
  648. }
  649.  
  650.  
  651. static void uafloat(struct GlobalVars *gv,struct ParsedLine *pl,bool dbl)
  652. {
  653.   char *s = pl->operand;
  654.   char *sb,c;
  655.   uint8 pass = gv->pass;
  656.   double f;
  657.  
  658.   for (;;) {
  659.     c = *s;
  660.     if (c==0 || c=='#') {
  661.       error(17);  /* missing argument */
  662.       break;
  663.     }
  664.     if (!pass) {
  665.       s = skipexpression(gv,s);
  666.       pcadd(gv,dbl?8:4);
  667.     }
  668.     else {
  669.       sscanf(s,"%lf",&f);
  670.       if (dbl)
  671.         store_double(gv,f);
  672.       else
  673.         store_float(gv,f);
  674.       s = skipexpression(gv,s);
  675.     }
  676.  
  677.     c = *s++;
  678.     if (c==0 || c=='#')  /* no more arguments? */
  679.       break;
  680.     if (c != ',') {
  681.       error(12);  /* colon expected */
  682.       break;
  683.     }
  684.     s = skipspaces(s);
  685.   }
  686. }
  687.  
  688.  
  689. static void _globl(struct GlobalVars *gv,struct ParsedLine *pl)
  690. {
  691.   char *s;
  692.   struct Symbol *sym;
  693.  
  694.   s = getsymbol(gv,pl->operand);
  695.   if (*gv->strbuf) {
  696.     if (!(sym = search_symbol(gv,gv->strbuf))) {
  697.       /* unknown in pass 1, then declare as externally defined first */
  698.       sym = add_symbol(gv,gv->strbuf,SYM_EXTERN,0);
  699.     }
  700.     sym->bind = SYMB_GLOBAL;
  701.     checkEOL(s);
  702.   }
  703.   else
  704.     error(17);  /* missing argument */
  705.   pl->type = OT_IGNORE;  /* ignore in pass 2 */
  706. }
  707.  
  708.  
  709. static void _local(struct GlobalVars *gv,struct ParsedLine *pl)
  710. {
  711.   char *s;
  712.   struct Symbol *sym;
  713.  
  714.   if (gv->pass) {
  715.     s = getsymbol(gv,pl->operand);
  716.     if (*gv->strbuf) {
  717.       if (!(sym = search_symbol(gv,gv->strbuf)))
  718.         error(19);  /* undefined symbol */
  719.       else
  720.         sym->bind = SYMB_LOCAL;
  721.       checkEOL(s);
  722.     }
  723.     else
  724.       error(17);  /* missing argument */
  725.   }
  726. }
  727.  
  728.  
  729. static void _bss(struct GlobalVars *gv,struct ParsedLine *pl)
  730. {
  731.   static char *bssname=".bss";
  732.   char *s;
  733.   struct Section *bss,*old=gv->csect;
  734.   uint32 size,align;
  735.   char symbname[STRBUFSIZE];
  736.   struct Symbol *sym;
  737.  
  738.   s = getsymbol(gv,pl->operand);
  739.   if (*gv->strbuf) {
  740.     if (!gv->pass)
  741.       strcpy(symbname,gv->strbuf);
  742.     if (!(s = check_comma(s)))
  743.       return;
  744.     s = getintexp(gv,s,&size);  /* size of bss symbol */
  745.     align = (size>=8)? 3 : 2;
  746.     s = skipspaces(s);
  747.     if (*s == ',') {
  748.       s = getintexp(gv,++s,&align);  /* optional aligment */
  749.       if (align < 2)
  750.         align = 2;
  751.     }
  752.     if (bss = search_section(gv,bssname)) {
  753.       activate_section(gv,bss);
  754.       alignment(gv,align);
  755.       if (!gv->pass) {
  756.         sym = add_symbol(gv,symbname,SYM_RELOC,bss->pc);
  757.         sym->info = SYMI_OBJECT;
  758.         sym->size = size;
  759.         sym->bind = SYMB_LOCAL;
  760.         pcadd(gv,size);
  761.         checkEOL(s);
  762.       }
  763.       else
  764.         store_space(gv,size);
  765.       activate_section(gv,old);
  766.     }
  767.     else
  768.       error(47,bssname);  /* section .bss was never defined */
  769.   }
  770.   else
  771.     error(17);  /* missing argument */
  772. }
  773.  
  774.  
  775. static void _comm(struct GlobalVars *gv,struct ParsedLine *pl)
  776. {
  777.   static char *bssname=".bss";
  778.   char *s;
  779.   struct Section *bss,*old=gv->csect;
  780.   uint32 size;
  781.   char symbname[STRBUFSIZE];
  782.   struct Symbol *sym;
  783.  
  784.   s = getsymbol(gv,pl->operand);
  785.   if (*gv->strbuf) {
  786.     if (!gv->pass)
  787.       strcpy(symbname,gv->strbuf);
  788.     if (!(s = check_comma(s)))
  789.       return;
  790.     s = getintexp(gv,s,&size);  /* size of bss symbol */
  791.     if (bss = search_section(gv,bssname)) {
  792.       activate_section(gv,bss);
  793.       alignment(gv,(size>=8)? 3:2);
  794.       if (!gv->pass) {
  795.         sym = add_symbol(gv,symbname,SYM_RELOC,bss->pc);
  796.         sym->info = SYMI_OBJECT;
  797.         sym->size = size;
  798.         sym->bind = SYMB_GLOBAL;  /* or SYMB_WEAK ?? */
  799.         pcadd(gv,size);
  800.         checkEOL(s);
  801.       }
  802.       else
  803.         store_space(gv,size);
  804.       activate_section(gv,old);
  805.     }
  806.     else
  807.       error(47,bssname);  /* section .bss was never defined */
  808.   }
  809.   else
  810.     error(17);  /* missing argument */
  811. }
  812.  
  813.  
  814. static void _type(struct GlobalVars *gv,struct ParsedLine *pl)
  815. {
  816.   char *s;
  817.   struct Symbol *sym;
  818.   uint32 type;
  819.  
  820.   if (gv->pass) {
  821.     s = getsymbol(gv,pl->operand);
  822.     if (*gv->strbuf) {
  823.       if (sym = search_symbol(gv,gv->strbuf)) {
  824.         if (s = check_comma(s)) {
  825.           s = getintexp(gv,s,&type);
  826.           sym->info = (uint8)type;
  827.           checkEOL(s);
  828.         }
  829.       }
  830.       else
  831.         error(19);  /* undefined symbol */
  832.     }
  833.     else
  834.       error(17);  /* missing argument */
  835.   }
  836. }
  837.  
  838.  
  839. static void _size(struct GlobalVars *gv,struct ParsedLine *pl)
  840. {
  841.   char *s;
  842.   struct Symbol *sym;
  843.   uint32 size;
  844.  
  845.   if (gv->pass) {
  846.     s = getsymbol(gv,pl->operand);
  847.     if (*gv->strbuf) {
  848.       if (sym = search_symbol(gv,gv->strbuf)) {
  849.         if (s = check_comma(s)) {
  850.           s = getintexp(gv,s,&size);
  851.           sym->size = size;
  852.           checkEOL(s);
  853.         }
  854.       }
  855.       else
  856.         error(19);  /* undefined symbol */
  857.     }
  858.     else
  859.       error(17);  /* missing argument */
  860.   }
  861. }
  862.  
  863.  
  864. static void _ifeq(struct GlobalVars *gv,struct ParsedLine *pl)
  865. {
  866.   ifeqs(gv,pl,0);
  867. }
  868.  
  869.  
  870. static void _ifne(struct GlobalVars *gv,struct ParsedLine *pl)
  871. {
  872.   ifeqs(gv,pl,1);
  873. }
  874.  
  875.  
  876. static void _ifgt(struct GlobalVars *gv,struct ParsedLine *pl)
  877. {
  878.   ifeqs(gv,pl,2);
  879. }
  880.  
  881.  
  882. static void _ifge(struct GlobalVars *gv,struct ParsedLine *pl)
  883. {
  884.   ifeqs(gv,pl,3);
  885. }
  886.  
  887.  
  888. static void _iflt(struct GlobalVars *gv,struct ParsedLine *pl)
  889. {
  890.   ifeqs(gv,pl,4);
  891. }
  892.  
  893.  
  894. static void _ifle(struct GlobalVars *gv,struct ParsedLine *pl)
  895. {
  896.   ifeqs(gv,pl,5);
  897. }
  898.  
  899.  
  900. static void ifeqs(struct GlobalVars *gv,struct ParsedLine *pl,int cond)
  901. {
  902.   char *s;
  903.   int32 val;
  904.   bool *condptr;
  905.  
  906.   if (gv->iflevel < (MAX_IFLEVELS-1)) {
  907.     condptr = &gv->ifcond[++gv->iflevel];
  908.     *condptr = FALSE;
  909.     s = getintexp(gv,pl->operand,&val);
  910.     switch (cond) {
  911.       case 0: /* eq */
  912.         if (val==0)
  913.           *condptr = TRUE;
  914.         break;
  915.       case 1: /* ne */
  916.         if (val!=0)
  917.           *condptr = TRUE;
  918.         break;
  919.       case 2: /* gt */
  920.         if (val>0)
  921.           *condptr = TRUE;
  922.         break;
  923.       case 3: /* ge */
  924.         if (val>=0)
  925.           *condptr = TRUE;
  926.         break;
  927.       case 4: /* lt */
  928.         if (val<0)
  929.           *condptr = TRUE;
  930.         break;
  931.       case 5: /* le */
  932.         if (val<=0)
  933.           *condptr = TRUE;
  934.         break;
  935.     }
  936.     checkEOL(s);
  937.   }
  938.   else
  939.     error(43);  /* maximum nesting depth for conditional assembly exceeded */
  940.   pl->type = OT_IGNORE;  /* ignore in pass 2 */
  941. }
  942.  
  943.  
  944. static void _ifdef(struct GlobalVars *gv,struct ParsedLine *pl)
  945. {
  946.   ifdef(gv,pl,TRUE);
  947. }
  948.  
  949.  
  950. static void _ifndef(struct GlobalVars *gv,struct ParsedLine *pl)
  951. {
  952.   ifdef(gv,pl,FALSE);
  953. }
  954.  
  955.  
  956. static void ifdef(struct GlobalVars *gv,struct ParsedLine *pl,bool c)
  957. {
  958.   char *s;
  959.   bool *condptr;
  960.  
  961.   if (gv->iflevel < (MAX_IFLEVELS-1)) {
  962.     condptr = &gv->ifcond[++gv->iflevel];
  963.     *condptr = c ? FALSE:TRUE;
  964.     s = getsymbol(gv,pl->operand);
  965.     if (*gv->strbuf)
  966.       if (search_symbol(gv,gv->strbuf))
  967.         *condptr = c;
  968.     checkEOL(s);
  969.   }
  970.   else
  971.     error(43);  /* maximum nesting depth for conditional assembly exceeded */
  972.   pl->type = OT_IGNORE;  /* ignore in pass 2 */
  973. }
  974.  
  975.  
  976. static void _else(struct GlobalVars *gv,struct ParsedLine *pl)
  977. {
  978.   if (gv->iflevel > 0) {
  979.     gv->ifcond[gv->iflevel] = FALSE;
  980.     checkEOL(pl->operand);
  981.   }
  982.   else
  983.     error(44,".else");  /* .else without matching .if */
  984.   pl->type = OT_IGNORE;  /* ignore in pass 2 */
  985. }
  986.  
  987.  
  988. static void _endif(struct GlobalVars *gv,struct ParsedLine *pl)
  989. {
  990.   if (gv->iflevel > 0) {
  991.     gv->iflevel--;
  992.     checkEOL(pl->operand);
  993.   }
  994.   else
  995.     error(44,".endif");  /* .endif without matching .if */
  996.   pl->type = OT_IGNORE;  /* ignore in pass 2 */
  997. }
  998.  
  999.  
  1000. static void _fail(struct GlobalVars *gv,struct ParsedLine *pl)
  1001. {
  1002.   error(45);  /* fail directive encountered */
  1003. }
  1004.  
  1005.  
  1006. static void _noop(struct GlobalVars *gv,struct ParsedLine *pl)
  1007. {
  1008. }
  1009.  
  1010.  
  1011. static void _ident(struct GlobalVars *gv,struct ParsedLine *pl)
  1012. {
  1013.   char *s = getarg(gv,pl->operand);  /* identification / comment */
  1014.  
  1015.   gv->ident = allocstring(remquotes(gv->strbuf));
  1016.   checkEOL(s);
  1017.   pl->type = OT_IGNORE;  /* ignore in pass 2 */
  1018. }
  1019.  
  1020.  
  1021. static void _file(struct GlobalVars *gv,struct ParsedLine *pl)
  1022. {
  1023.   char *s = getarg(gv,pl->operand);  /* source file name */
  1024.  
  1025.   gv->file = allocstring(remquotes(gv->strbuf));
  1026.   checkEOL(s);
  1027.   pl->type = OT_IGNORE;  /* ignore in pass 2 */
  1028. }
  1029.  
  1030.  
  1031. static void _baserel(struct GlobalVars *gv,struct ParsedLine *pl)
  1032. /* OBSOLETE SINCE V1.1. */
  1033. /* The .baserel directive only exists for compatibilty with older sources */
  1034. {
  1035.   char *s;
  1036.   struct Symbol *sym;
  1037.   uint32 tocreg;
  1038.  
  1039.   if (gv->pass) {
  1040.     s = getsymbol(gv,pl->operand);
  1041.     if (*gv->strbuf) {
  1042.       if (sym = search_symbol(gv,gv->strbuf)) {
  1043.         if (s = check_comma(s)) {
  1044.           s = getintexp(gv,s,&tocreg);
  1045.           if (sym->info == SYMI_SECTION) {
  1046.             /* activate new base relative addressing mode */
  1047.             gv->tocsect = sym->relsect;
  1048.             gv->rtoc = (int)tocreg;
  1049.           }
  1050.           else
  1051.             error(50,sym->name);  /* symbol is not a section base address */
  1052.           checkEOL(s);
  1053.         }
  1054.       }
  1055.       else
  1056.         error(19);  /* undefined symbol */
  1057.     }
  1058.     else
  1059.       error(17);  /* missing argument */
  1060.   }
  1061. }
  1062.  
  1063.  
  1064. static void _sdreg(struct GlobalVars *gv,struct ParsedLine *pl)
  1065. {
  1066.   char *s;
  1067.   uint32 tocreg;
  1068.  
  1069.   if (gv->pass) {
  1070.     s = getintexp(gv,pl->operand,&tocreg);
  1071.     if (tocreg < 32) {
  1072.       gv->rtoc = (int)tocreg;
  1073.       gv->tocsect = NULL;  /* disable single sd-section mode */
  1074.     }
  1075.     else
  1076.       error(31);  /* wrong register */
  1077.     checkEOL(s);
  1078.   }
  1079. }
  1080.  
  1081.  
  1082. struct Directive directives[] = {
  1083.   0,".new_section",_new_section,
  1084.   0,".section",_section,
  1085.   0,".set",_set,
  1086.   0,".macro",_macro,
  1087.   0,".include",_include,
  1088.   0,".align",_align,
  1089.   0,".space",_space,
  1090.   0,".byte",_byte,
  1091.   0,".ascii",_byte,
  1092.   0,".string",_string,
  1093.   0,".asciiz",_string,
  1094.   0,".half",_half,
  1095.   0,".short",_half,
  1096.   0,".word",_word,
  1097.   0,".long",_word,
  1098.   0,".float",_float,
  1099.   0,".double",_double,
  1100.   0,".uahalf",_uahalf,
  1101.   0,".uashort",_uahalf,
  1102.   0,".uaword",_uaword,
  1103.   0,".ualong",_uaword,
  1104.   0,".uafloat",_uafloat,
  1105.   0,".uadouble",_uadouble,
  1106.   0,".globl",_globl,
  1107.   0,".global",_globl,
  1108.   0,".extern",_globl,
  1109.   0,".local",_local,
  1110.   0,".bss",_bss,
  1111.   0,".lcomm",_bss,
  1112.   0,".comm",_comm,
  1113.   0,".type",_type,
  1114.   0,".size",_size,
  1115.   0,".if",_ifne,
  1116.   0,".ifeq",_ifeq,
  1117.   0,".ifne",_ifne,
  1118.   0,".ifgt",_ifgt,
  1119.   0,".ifge",_ifge,
  1120.   0,".iflt",_iflt,
  1121.   0,".ifle",_ifle,
  1122.   0,".ifdef",_ifdef,
  1123.   0,".ifndef",_ifndef,
  1124.   0,".else",_else,
  1125.   0,".endif",_endif,
  1126.   0,".fail",_fail,
  1127.   0,".ident",_ident,
  1128.   0,".file",_file,
  1129.   0,".baserel",_baserel,
  1130.   0,".sdreg",_sdreg,
  1131.   0,0 /* end mark */
  1132. };
  1133.